package implementation1.app.commands;

import exceptions.CommandException;
import exceptions.CreatingProcessException;
import exceptions.StreamException;
import implementation1.app.Analyzer;
import implementation1.app.streams.PipeStream;
import implementation1.data.Handle;
import interfaces.app.IProcess;
import interfaces.app.IStream;
import interfaces.data.IHandle;

/**
 * Class for handle of fictive command for creating pipe between two processes.
 * Created: 25.10.11
 *
 * @author Jan Svab
 */
public class Pipe extends Command
{
    /**
     * Default constructor.
     *
     * @param parent parent process over which is command processed
     * @param handle parameters of command
     */
    public Pipe(IProcess parent, IHandle handle)
    {
        super(parent, handle);
    }

    /**
     * Main method for processing of command.
     *
     * @param args arguments of command
     */
    @Override
    public void mainCommand(String[] args) throws CommandException
    {
        if (args.length != 2)
        {
            throw new CommandException("error.pipe.arguments");
        }
        //processing of first command
        Analyzer analyzer = new Analyzer();
        analyzer.setCommand(args[0]);
        analyzer.setBasePath(handle.getActualPath());
        String name = analyzer.getCommandName();
        String[] arg = analyzer.getArguments();

        PipeStream pipeStream = new PipeStream();

        Handle handleFirstCommand = null;
        try
        {
            IStream in = analyzer.getInput() != null ? analyzer.getInput() : handle.getIn();
            IStream out = pipeStream;
            IStream err = analyzer.getErrorOutput() != null ? analyzer.getErrorOutput() : handle.getErrorOut();

            handleFirstCommand = new Handle(arg, in, out, err, name, handle.getActualPath(), handle.getAccount());
        } catch (StreamException e)
        {
            throw new CommandException("'" + analyzer.getCommandName() + "': " + e.getMessage());
        }

        //processing of second command
        analyzer = new Analyzer();
        analyzer.setCommand(args[1]);
        analyzer.setBasePath(handle.getActualPath());
        name = analyzer.getCommandName();
        arg = analyzer.getArguments();

        Handle handleSecondCommand = null;
        try
        {
            IStream in = pipeStream;
            IStream out = analyzer.getOutput() != null ? analyzer.getOutput() : handle.getOut();
            IStream err = analyzer.getErrorOutput() != null ? analyzer.getErrorOutput() : handle.getErrorOut();

            handleSecondCommand = new Handle(arg, in, out, err, name, handle.getActualPath(), handle.getAccount());
        } catch (StreamException e)
        {
            throw new CommandException("'" + analyzer.getCommandName() + "': " + e.getMessage());
        }

        try
        {
            IProcess firstCmd = createChildProcess(handleFirstCommand);
            IProcess secondCmd = createChildProcess(handleSecondCommand);

            firstCmd.startProcess();
            secondCmd.startProcess();

            waitToChild(firstCmd.getPid());

            if (this.hasEndStatus())
            {
                return;
            }

            if (!secondCmd.hasEndStatus())
            {
                waitToChild(secondCmd.getPid());
            }
        } catch (CreatingProcessException e)
        {
            throw new CommandException(e.getMessage());
        }

        parentProcess.getHandle().setActualPath(this.getHandle().getActualPath());
    }

    @Override
    public String toString()
    {
        return "pipe";
    }
}
